﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Wiki.Models;
using Core;
using System.Reflection;

namespace Wiki.Controllers
{
    [Permission("Can Contribute Documents")]
    public class AdminController : Controller
    {
        //
        // GET: /Admin/

        [Permission("Can Modify Domain")]
        public ActionResult Index()
        {
            WikiEntities wiki = new WikiEntities();
            Guid BUId = (Guid)Session["BusinessUnitId"];
            ViewBag.BusinessUnitId = BUId;
            return View();
        }

        //
        // POST: /WikiList/

        [HttpPost]
        public JsonResult WikiList(FormCollection collection)
        {
            Models.WikiEntities we = new WikiEntities();
            Guid BUId = new Guid(collection.GetValues("BusinessUnitId")[0].ToString());
            int SkipRecs = int.Parse(collection.GetValues("iDisplayStart")[0].ToString());
            int TakeCount = int.Parse(collection.GetValues("iDisplayLength")[0].ToString());
            string strSearch = collection.GetValues("sSearch")[0].ToString();
            DataTableResponse r = new DataTableResponse();
            // Needs update when paging & sorting is implemented
            List<Models.Wiki> wikilist = we.Wikis.Where(m => (m.BusinessUnitId == BUId && m.WikiName.Contains(strSearch) && m.IsDroppedYN == "N")).OrderBy(m => m.CreateDT).Skip(SkipRecs).Take(TakeCount).ToList();
            r.sEcho = collection.GetValues("sEcho")[0].ToString();
            // This query is required because the earlier query returns results for only 1 page.
            r.iTotalRecords = we.Wikis.Where(m => (m.BusinessUnitId == BUId && m.WikiName.Contains(strSearch) && m.IsDroppedYN == "N")).Count();
            r.iTotalDisplayRecords = r.iTotalRecords;
            foreach (Models.Wiki wiki in wikilist)
            {
                List<string> r1 = new List<string>();
                string editurl = String.Format("<a href=\"/{0}/{1}/{2}\" id=\"editlink\" title=\"{1}\" >Edit</a>", "Wiki/Admin", "Edit", wiki.WikiId.ToString());
                string detailsurl = String.Format("<a href=\"/{0}/{1}/{2}\" id=\"detailslink\" title=\"{1}\" >Details</a>", "Wiki/Admin", "Details", wiki.WikiId.ToString());
                string deleteurl = String.Format("<a href=\"/{0}/{1}/{2}\" id=\"deletelink\" title=\"{1}\" >Delete</a>", "Wiki/Admin", "Delete", wiki.WikiId.ToString());
                string pagesurl = String.Format("<a href=\"/{0}/{1}/{2}\" >Pages</a>", "Wiki/Admin", "Pages", wiki.WikiId.ToString());
                r1.Add(editurl + detailsurl + deleteurl + pagesurl);
                r1.Add(wiki.WikiName);
                r1.Add(String.Format("{0:g}", wiki.ModifiedDT));
                r1.Add(wiki.ModifiedByName);
                r1.Add(wiki.CreatedByName);
                r.aaData.Add(r1);
            }
            return Json(r);
        }

        //
        // GET: /Create/

        [Permission("Can Modify Domain")]
        public ActionResult Create()
        {
            WikiEntities we = new WikiEntities();
            Wiki.Models.WikiCreate w = new WikiCreate();
            w.BusinessUnitId = (Guid)Session["BusinessUnitId"];
            w.OnMainMenuYN = "N";
            w.PermissionId = we.Permissions.First(m => m.Name == "Can Use Anonymously").PermissionId;

            List<Permission> plist = we.Permissions.ToList();
            ViewBag.PermissionList = plist;

            return View(w);
        }

        //
        // POST: /Create/

        [HttpPost]
        [Permission("Can Modify Domain")]
        public ActionResult Create(WikiCreate w)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    WikiEntities we = new WikiEntities();

                    // Create all the Guids to maintain referential integrity
                    string WikiName = w.WikiName;
                    Guid WikiPageId = Guid.NewGuid();
                    Guid PageId = Guid.NewGuid();
                    Guid WikiId = Guid.NewGuid();
                    Guid PluginId = new Guid(((System.Runtime.InteropServices.GuidAttribute)(Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), false)[0])).Value);
                    Guid ContainerId = GetContainerId(we, WikiName, PluginId);

                    // Create Wiki
                    Wiki.Models.Wiki wiki = new Models.Wiki();
                    wiki.WikiId = WikiId;
                    wiki.BusinessUnitId = w.BusinessUnitId;
                    wiki.WikiName = w.WikiName;
                    wiki.WikiHomePageId = WikiPageId;
                    wiki.IsDroppedYN = "N";
                    wiki.CreateDT = DateTime.Now;
                    wiki.CreatedById = (Guid)Session["UserId"];
                    wiki.CreatedByName = Session["UserFullName"].ToString();
                    wiki.ModifiedDT = DateTime.Now;
                    wiki.ModifiedById = (Guid)Session["UserId"];
                    wiki.ModifiedByName = Session["UserFullName"].ToString();

                    // Create Wiki Page
                    WikiPage wp = new WikiPage();
                    wp.WikiPageId = WikiPageId;
                    wp.WikiId = WikiId;
                    wp.PageId = PageId;
                    wp.Title = "Home";
                    wp.ContentText = w.ContentText.Replace("<br />", "").Replace("<p>", "").Replace("</p>", "").Replace("&amp;", "&").Replace("&nbsp;", " ");
                    wp.IsDroppedYN = "N";
                    wp.CreateDT = DateTime.Now;
                    wp.CreatedById = (Guid)Session["UserId"];
                    wp.CreatedByName = Session["UserFullName"].ToString();
                    wp.ModifiedDT = DateTime.Now;
                    wp.ModifiedById = (Guid)Session["UserId"];
                    wp.ModifiedByName = Session["UserFullName"].ToString();

                    // Create Page
                    Wiki.Models.Page p = new Page();
                    p.PageId = PageId;
                    p.BusinessUnitId = w.BusinessUnitId;
                    p.PermissionId = w.PermissionId;
                    p.PageName = w.PageName;
                    p.Title = w.WikiName;
                    p.ShowTitleYN = "N";
                    p.MetaKeywords = w.MetaKeywords;
                    p.MetaDescription = w.MetaDescription;
                    p.ContainerId = ContainerId;
                    p.OnMainMenuYN = w.OnMainMenuYN;
                    p.IsTemplateYN = "N";
                    p.IsDroppedYN = "N";
                    p.CreateDT = DateTime.Now;
                    p.CreatedById = (Guid)Session["UserId"];
                    p.CreatedByName = Session["UserFullName"].ToString();
                    p.ModifiedDT = DateTime.Now;
                    p.ModifiedById = (Guid)Session["UserId"];
                    p.ModifiedByName = Session["UserFullName"].ToString();

                    // Create Template Overide
                    TemplateOveride to = new TemplateOveride();
                    to.TemplateOverideId = Guid.NewGuid();
                    to.PageId = PageId;
                    to.TemplateContentId = PluginId;
                    to.OverideContentId = WikiPageId;
                    to.IsDroppedYN = "N";
                    to.ModifiedDT = DateTime.Now;
                    p.TemplateOverides.Add(to);

                    // Add the entities to the model and save changes
                    we.AddToWikis(wiki);
                    we.AddToWikiPages(wp);
                    we.AddToPages(p);
                    we.SaveChanges();

                    // Create Mainmenu entry if Specified
                    if (p.OnMainMenuYN == "Y")
                    {
                        Core.Models.MainMenu menu = new Core.Models.MainMenu();
                        menu.MenuItemId = Guid.NewGuid();
                        menu.DomainId = (Guid)Session["DomainId"];
                        menu.Name = p.Title;
                        menu.URL = p.PageName.Substring(1);
                        menu.UserPermission = we.Permissions.First(m => m.PermissionId == p.PermissionId).Name;
                        menu.Sequence = 1;
                        menu.HideOnSmallDeviceYN = "N";
                        menu.IsDroppedYN = "N";
                        menu.CreateDT = DateTime.Now;
                        menu.CreatedById = (Guid)Session["UserId"];
                        menu.CreatedByName = Session["UserFullName"].ToString();
                        menu.ModifiedDT = DateTime.Now;
                        menu.ModifiedById = (Guid)Session["UserId"];
                        menu.ModifiedByName = Session["UserFullName"].ToString();
                        Core.Models.CoreEntities core = new Core.Models.CoreEntities();
                        core.AddToMainMenus(menu);
                        core.SaveChanges();
                    }

                    // Index the content
                    Core.Search.SearchDoc doc = new Core.Search.SearchDoc();
                    doc.DocId = p.PageId;
                    doc.BusinessUnitId = Guid.Empty; // Search convention is Guid.EWmpty if Domain wide access
                    doc.PluginId = PluginId;
                    doc.URL = p.PageName.Substring(1);
                    doc.Title = p.Title;
                    doc.Keywords = p.MetaKeywords;
                    doc.Description = p.MetaDescription;
                    doc.Content = Core.Tools.GetTextFromHtml(wp.ContentText);
                    Core.Search.SearchEngine se = new Core.Search.SearchEngine((Guid)Session["DomainId"]);
                    se.IndexContent(doc);
                    return RedirectToAction("Index");
                }
                catch (Exception e)
                {   
                    ModelState.AddModelError("", Tools.ExceptionMessage(e));
                }
            }
            return View(w);
        }

        private Guid GetContainerId(WikiEntities we, string WikiName, Guid PluginId)
        {
            Guid ContainerId;
            List<Container> clist = we.Containers.Where(m => (m.ContainerName == "Wiki Template Container" && m.PluginId == PluginId && m.IsDroppedYN == "N")).ToList();
            if (clist.Count <= 0)
            {
                // Create Container Entity
                ContainerId = Guid.NewGuid();
                Container container = new Container();
                container.ContainerId = ContainerId;
                container.ContainerType = "C";
                container.ShowChromeYN = "N";
                container.ContainerName = "Wiki Template Container";
                container.Title = WikiName;
                container.Width = 0;
                container.ParentContainerId = null;
                container.PluginId = PluginId;
                container.ContentId = PluginId;
                container.IsDroppedYN = "N";
                container.CreateDT = DateTime.Now;
                container.CreatedById = (Guid)Session["UserId"];
                container.CreatedByName = Session["UserFullName"].ToString();
                container.ModifiedDT = DateTime.Now;
                container.ModifiedById = (Guid)Session["UserId"];
                container.ModifiedByName = Session["UserFullName"].ToString();
                we.AddToContainers(container);
                we.SaveChanges();
            }
            else
            {
                ContainerId = clist[0].ContainerId;
            }
            return ContainerId;
        }

        //
        // GET: /Edit/

        [Permission("Can Modify Domain")]
        public ActionResult Edit(Guid id)
        {
            WikiEntities we = new WikiEntities();
            Models.Wiki wiki = we.Wikis.First(m => (m.WikiId == id && m.IsDroppedYN == "N"));
            Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == wiki.WikiHomePageId && m.IsDroppedYN == "N"));
            Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
            Wiki.Models.WikiCreate w = new WikiCreate();
            w.WikiId = wiki.WikiId;
            w.BusinessUnitId = wiki.BusinessUnitId;
            w.WikiHomePageId = wiki.WikiHomePageId;
            w.WikiName = wiki.WikiName;
            w.PageName = p.PageName;
            w.MetaKeywords = p.MetaKeywords;
            w.MetaDescription = p.MetaDescription;
            w.OnMainMenuYN = p.OnMainMenuYN;
            w.PermissionId = p.PermissionId;
            w.ContentText = wp.ContentText.Replace("\r\n","<br />");
            List<Permission> plist = we.Permissions.ToList();
            ViewBag.PermissionList = plist;
            return View(w);
        }

        //
        // POST: /Edit/

        [HttpPost]
        [Permission("Can Modify Domain")]
        public ActionResult Edit(WikiCreate w)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    WikiEntities we = new WikiEntities();

                    // Create all the Guids to maintain referential integrity
                    Guid WikiPageId = w.WikiHomePageId;
                    Guid WikiId = w.WikiId;
                    Guid PluginId = new Guid(((System.Runtime.InteropServices.GuidAttribute)(Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), false)[0])).Value);

                    Models.Wiki wiki = we.Wikis.First(m => (m.WikiId == WikiId && m.IsDroppedYN == "N"));
                    wiki.WikiName = w.WikiName;
                    wiki.ModifiedDT = DateTime.Now;
                    wiki.ModifiedById = (Guid)Session["UserId"];
                    wiki.ModifiedByName = Session["UserFullName"].ToString();

                    Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == wiki.WikiHomePageId && m.IsDroppedYN == "N"));
                    wp.ContentText = w.ContentText.Replace("<br />", "").Replace("<p>", "").Replace("</p>", "").Replace("&amp;", "&").Replace("&nbsp;", " ");
                    wp.ModifiedDT = DateTime.Now;
                    wp.ModifiedById = (Guid)Session["UserId"];
                    wp.ModifiedByName = Session["UserFullName"].ToString();

                    Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
                    string pOnMainMenuYN = p.OnMainMenuYN;
                    string pPageName = p.PageName;
                    p.Title = w.WikiName;
                    p.PageName = w.PageName;
                    p.MetaKeywords = w.MetaKeywords;
                    p.MetaDescription = w.MetaDescription;
                    p.OnMainMenuYN = w.OnMainMenuYN;
                    p.PermissionId = w.PermissionId;
                    p.ModifiedDT = DateTime.Now;
                    p.ModifiedById = (Guid)Session["UserId"];
                    p.ModifiedByName = Session["UserFullName"].ToString();

                    we.SaveChanges();

                    // Update the MainMenu entry, create one if required.
                    if (pOnMainMenuYN != p.OnMainMenuYN)
                    {
                        Core.Models.CoreEntities core = new Core.Models.CoreEntities();
                        string pMenuUrl = pPageName.Substring(1);
                        List<Core.Models.MainMenu> mlist = core.MainMenus.Where(m => (m.URL == pMenuUrl && m.IsDroppedYN == "N")).ToList();
                        if (p.OnMainMenuYN == "Y" && mlist.Count <= 0)
                        {
                            Core.Models.MainMenu menu = new Core.Models.MainMenu();
                            menu.MenuItemId = Guid.NewGuid();
                            menu.DomainId = (Guid)Session["DomainId"];
                            menu.Name = p.Title;
                            menu.URL = p.PageName.Substring(1);
                            menu.UserPermission = we.Permissions.First(m => m.PermissionId == p.PermissionId).Name;
                            menu.Sequence = 1;
                            menu.IsDroppedYN = "N";
                            menu.CreateDT = DateTime.Now;
                            menu.CreatedById = (Guid)Session["UserId"];
                            menu.CreatedByName = Session["UserFullName"].ToString();
                            menu.ModifiedDT = DateTime.Now;
                            menu.ModifiedById = (Guid)Session["UserId"];
                            menu.ModifiedByName = Session["UserFullName"].ToString();
                            core.AddToMainMenus(menu);
                            core.SaveChanges();
                        }
                        else
                        {
                            Core.Models.MainMenu menu = mlist[0];
                            menu.IsDroppedYN = p.OnMainMenuYN == "Y" ? "N" : "Y";
                            menu.ModifiedDT = DateTime.Now;
                            menu.ModifiedById = (Guid)Session["UserId"];
                            menu.ModifiedByName = Session["UserFullName"].ToString();
                            core.SaveChanges();
                        }
                    }

                    // Index the content
                    Core.Search.SearchDoc doc = new Core.Search.SearchDoc();
                    doc.DocId = p.PageId;
                    doc.BusinessUnitId = Guid.Empty; // Search convention is Guid.EWmpty if Domain wide access
                    doc.PluginId = PluginId;
                    doc.URL = p.PageName.Substring(1);
                    doc.Title = p.Title;
                    doc.Keywords = p.MetaKeywords;
                    doc.Description = p.MetaDescription;
                    doc.Content = Core.Tools.GetTextFromHtml(wp.ContentText);
                    Core.Search.SearchEngine se = new Core.Search.SearchEngine((Guid)Session["DomainId"]);
                    se.IndexContent(doc);

                    return RedirectToAction("Index");
                }
            }
            catch (Exception e)
            {
                ModelState.AddModelError("",Tools.ExceptionMessage(e));
            }
            return View(w);
        }

        //
        // GET: /Details/

        [Permission("Can Modify Domain")]
        public ActionResult Details(Guid id)
        {
            WikiEntities we = new WikiEntities();
            Models.Wiki wiki = we.Wikis.First(m => (m.WikiId == id && m.IsDroppedYN == "N"));
            Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == wiki.WikiHomePageId && m.IsDroppedYN == "N"));
            Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
            Wiki.Models.WikiCreate w = new WikiCreate();
            w.WikiId = wiki.WikiId;
            w.BusinessUnitId = wiki.BusinessUnitId;
            w.WikiHomePageId = wiki.WikiHomePageId;
            w.WikiName = wiki.WikiName;
            w.PageName = p.PageName;
            w.MetaKeywords = p.MetaKeywords;
            w.MetaDescription = p.MetaDescription;
            w.OnMainMenuYN = p.OnMainMenuYN;
            w.PermissionId = p.PermissionId;
            w.ContentText = wp.ContentText.Replace("\r\n", "<br />");
            ViewBag.PermissionName = we.Permissions.First(m => m.PermissionId == p.PermissionId).Name;
            return View(w);
        }

        //
        // GET: /Delete/

        [Permission("Can Modify Domain")]
        public ActionResult Delete(Guid id)
        {
            WikiEntities we = new WikiEntities();
            Models.Wiki wiki = we.Wikis.First(m => (m.WikiId == id && m.IsDroppedYN == "N"));
            Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == wiki.WikiHomePageId && m.IsDroppedYN == "N"));
            Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
            Wiki.Models.WikiCreate w = new WikiCreate();
            w.WikiId = wiki.WikiId;
            w.BusinessUnitId = wiki.BusinessUnitId;
            w.WikiHomePageId = wiki.WikiHomePageId;
            w.WikiName = wiki.WikiName;
            w.PageName = p.PageName;
            w.MetaKeywords = p.MetaKeywords;
            w.MetaDescription = p.MetaDescription;
            w.OnMainMenuYN = p.OnMainMenuYN;
            w.PermissionId = p.PermissionId;
            w.ContentText = wp.ContentText.Replace("\r\n", "<br />");
            ViewBag.PermissionName = we.Permissions.First(m => m.PermissionId == p.PermissionId).Name;
            return View(w);
        }

        //
        // POST: /Delete/

        [HttpPost]
        [Permission("Can Modify Domain")]
        public ActionResult Delete(WikiCreate w)
        {
            try
            {
                Guid WikiId = w.WikiId;

                WikiEntities we = new WikiEntities();
                Core.Models.CoreEntities core = new Core.Models.CoreEntities();
                Models.Wiki wiki = we.Wikis.First(m => m.WikiId == WikiId);
                List<Guid> list = we.WikiPages.Where(m => m.WikiId == WikiId).Select(m => m.WikiPageId).ToList();
                foreach(Guid WikiPageId in list)
                {
                    DeleteWikiPage(we, core, WikiPageId);
                }
                wiki.IsDroppedYN = "Y";
                wiki.ModifiedDT = DateTime.Now;
                wiki.ModifiedById = (Guid)Session["UserId"];
                wiki.ModifiedByName = Session["UserFullName"].ToString();
                we.SaveChanges();

                return RedirectToAction("Index");
            }
            catch (Exception e)
            {
                ModelState.AddModelError("", Tools.ExceptionMessage(e));
            }
            return View(w);
        }

        //
        // GET: /Pages/

        [Permission("Can Modify Domain")]
        public ActionResult Pages(Guid id)
        {
            WikiEntities we = new WikiEntities();
//            List<Models.WikiPage> list = we.WikiPages.Where(m => (m.WikiId == id && m.IsDroppedYN == "N")).ToList();
            ViewBag.WikiId = id;
            ViewBag.WikiName = we.Wikis.First(m => m.WikiId == id).WikiName;
            return View();
        }

        //
        // POST: /PageList/

        [HttpPost]
        public JsonResult PageList(FormCollection collection)
        {
            Models.WikiEntities we = new WikiEntities();
            Guid WikiId = new Guid(collection.GetValues("WikiId")[0].ToString());
            int SkipRecs = int.Parse(collection.GetValues("iDisplayStart")[0].ToString());
            int TakeCount = int.Parse(collection.GetValues("iDisplayLength")[0].ToString());
            string strSearch = collection.GetValues("sSearch")[0].ToString();
            DataTableResponse r = new DataTableResponse();
            // Needs update when paging & sorting is implemented
            List<Models.WikiPage> pagelist = we.WikiPages.Where(m => (m.WikiId == WikiId && m.Title.Contains(strSearch) && m.IsDroppedYN == "N")).OrderBy(m => m.CreateDT).Skip(SkipRecs).Take(TakeCount).ToList();
            r.sEcho = collection.GetValues("sEcho")[0].ToString();
            // This query is required because the earlier query returns results for only 1 page.
            r.iTotalRecords = we.WikiPages.Where(m => (m.WikiId == WikiId && m.Title.Contains(strSearch) && m.IsDroppedYN == "N")).Count();
            r.iTotalDisplayRecords = r.iTotalRecords;
            foreach (Models.WikiPage page in pagelist)
            {
                List<string> r1 = new List<string>();
                string editurl = String.Format("<a href=\"/{0}/{1}/{2}\" id=\"editlink\" title=\"{1}\" >Edit</a>", "Wiki/Admin", "PageEdit", page.WikiPageId.ToString());
                string detailsurl = String.Format("<a href=\"/{0}/{1}/{2}\" id=\"detailslink\" title=\"{1}\" >Details</a>", "Wiki/Admin", "PageDetails", page.WikiPageId.ToString());
                string deleteurl = String.Format("<a href=\"/{0}/{1}/{2}\" id=\"deletelink\" title=\"{1}\" >Delete</a>", "Wiki/Admin", "PageDelete", page.WikiPageId.ToString());
                string viewurl = String.Format("<a href=\"{0}\" >View</a>", we.Pages.First(m => m.PageId == page.PageId).PageName.Substring(1));
                r1.Add(editurl + detailsurl + deleteurl + viewurl);
                r1.Add(page.Title);
                r1.Add(String.Format("{0:g}", page.ModifiedDT));
                r1.Add(page.ModifiedByName);
/*                r1.Add(String.Format("{0:g}", page.CreateDT));
                r1.Add(page.CreatedByName); */
                r.aaData.Add(r1);
            }
            return Json(r);
        }

        //
        // GET: /CreatePage/

        [Permission("Can Modify Domain")]
        public ActionResult CreatePage(Guid id)
        {
            TempData["ReturnURL"] = Request.UrlReferrer.AbsolutePath.ToString();
            WikiEntities we = new WikiEntities();
            Models.Wiki wiki = we.Wikis.First(m => (m.WikiId == id && m.IsDroppedYN == "N"));
            Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == wiki.WikiHomePageId && m.IsDroppedYN == "N"));
            Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
            Wiki.Models.WikiPageUI w = new WikiPageUI();
            w.WikiId = wiki.WikiId;
            w.BusinessUnitId = wiki.BusinessUnitId;
            w.WikiHomePageId = wiki.WikiHomePageId;
            w.WikiName = wiki.WikiName;
            w.OnMainMenuYN = "N";
            w.PermissionId = we.Permissions.First(m => m.Name == "Can Use Anonymously").PermissionId;
            List<Permission> plist = we.Permissions.ToList();
            ViewBag.PermissionList = plist;
            return View(w);
        }

        //
        // POST: /CreatePage/

        [HttpPost]
        [Permission("Can Modify Domain")]
        public ActionResult CreatePage(WikiPageUI wui)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    WikiEntities we = new WikiEntities();

                    // Create all the Guids to maintain referential integrity
                    Guid WikiId = wui.WikiId;
                    Guid WikiPageId = Guid.NewGuid();
                    Guid PageId = Guid.NewGuid();
                    Guid PluginId = new Guid(((System.Runtime.InteropServices.GuidAttribute)(Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), false)[0])).Value);
                    Guid ContainerId = GetContainerId(we, wui.WikiName, PluginId);

                    // Create Wiki Page
                    WikiPage wp = new WikiPage();
                    wp.WikiPageId = WikiPageId;
                    wp.WikiId = WikiId;
                    wp.PageId = PageId;
                    wp.Title = wui.Title;
                    wp.ContentText = wui.ContentText.Replace("<br />", "").Replace("<p>", "").Replace("</p>", "").Replace("&amp;", "&").Replace("&nbsp;", " ");
                    wp.IsDroppedYN = "N";
                    wp.CreateDT = DateTime.Now;
                    wp.CreatedById = (Guid)Session["UserId"];
                    wp.CreatedByName = Session["UserFullName"].ToString();
                    wp.ModifiedDT = DateTime.Now;
                    wp.ModifiedById = (Guid)Session["UserId"];
                    wp.ModifiedByName = Session["UserFullName"].ToString();

                    // Create Page
                    Wiki.Models.Page p = new Page();
                    p.PageId = PageId;
                    p.BusinessUnitId = wui.BusinessUnitId;
                    p.PermissionId = wui.PermissionId;
                    p.PageName = wui.PageName;
                    p.Title = wui.Title;
                    p.ShowTitleYN = "N";
                    p.MetaKeywords = wui.MetaKeywords;
                    p.MetaDescription = wui.MetaDescription;
                    p.ContainerId = ContainerId;
                    p.OnMainMenuYN = "N";
                    p.IsTemplateYN = "N";
                    p.IsDroppedYN = "N";
                    p.CreateDT = DateTime.Now;
                    p.CreatedById = (Guid)Session["UserId"];
                    p.CreatedByName = Session["UserFullName"].ToString();
                    p.ModifiedDT = DateTime.Now;
                    p.ModifiedById = (Guid)Session["UserId"];
                    p.ModifiedByName = Session["UserFullName"].ToString();

                    // Create Template Overide
                    TemplateOveride to = new TemplateOveride();
                    to.TemplateOverideId = Guid.NewGuid();
                    to.PageId = PageId;
                    to.TemplateContentId = PluginId;
                    to.OverideContentId = WikiPageId;
                    to.IsDroppedYN = "N";
                    to.ModifiedDT = DateTime.Now; 
                    p.TemplateOverides.Add(to);

                    // Add the entities to the model and save changes
                    we.AddToWikiPages(wp);
                    we.AddToPages(p);
                    we.SaveChanges();

                    // Index the content
                    Core.Search.SearchDoc doc = new Core.Search.SearchDoc();
                    doc.DocId = p.PageId;
                    doc.BusinessUnitId = Guid.Empty; // Search convention is Guid.EWmpty if Domain wide access
                    doc.PluginId = PluginId;
                    doc.URL = p.PageName.Substring(1);
                    doc.Title = p.Title;
                    doc.Keywords = p.MetaKeywords;
                    doc.Description = p.MetaDescription;
                    doc.Content = Core.Tools.GetTextFromHtml(wp.ContentText);
                    Core.Search.SearchEngine se = new Core.Search.SearchEngine((Guid)Session["DomainId"]);
                    se.IndexContent(doc);

                    try
                    {
                        if (!String.IsNullOrEmpty(TempData["ReturnURL"].ToString()))
                            if (!TempData["ReturnURL"].ToString().Contains("Admin/Index"))
                                return Redirect(p.PageName.Substring(1));
                    }
                    catch
                    {
                    }
                    return RedirectToAction("Pages", new { id = wui.WikiId });
                }
                catch (Exception e)
                {
                    ModelState.AddModelError("", Tools.ExceptionMessage(e));
                }
            }
            return View(wui);
        }

        //
        // GET: /PageEdit/

        [Permission("Can Modify Domain")]
        public ActionResult PageEdit(Guid id)
        {
            TempData["ReturnURL"] = Request.UrlReferrer.AbsolutePath.ToString();
            WikiEntities we = new WikiEntities();
            Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == id && m.IsDroppedYN == "N"));
            Models.Wiki wiki = we.Wikis.First(m => (m.WikiId == wp.WikiId && m.IsDroppedYN == "N"));
            Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
            Wiki.Models.WikiPageUI w = new WikiPageUI();
            w.WikiPageId = wp.WikiPageId;
            w.Title = wp.Title;
            w.WikiId = wiki.WikiId;
            w.BusinessUnitId = wiki.BusinessUnitId;
            w.WikiHomePageId = wiki.WikiHomePageId;
            w.WikiName = wiki.WikiName;
            w.PageName = p.PageName;
            w.MetaKeywords = p.MetaKeywords;
            w.MetaDescription = p.MetaDescription;
            w.OnMainMenuYN = p.OnMainMenuYN;
            w.PermissionId = p.PermissionId;
            w.ContentText = wp.ContentText.Replace("\r\n", "<br />");
            List<Permission> plist = we.Permissions.ToList();
            ViewBag.PermissionList = plist;
            return View(w);
        }

        //
        // POST: /PageEdit/

        [HttpPost]
        [Permission("Can Modify Domain")]
        public ActionResult PageEdit(WikiPageUI w)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    WikiEntities we = new WikiEntities();

                    // Create all the Guids to maintain referential integrity
                    Guid WikiPageId = w.WikiPageId;
                    Guid WikiId = w.WikiId;
                    Guid PluginId = new Guid(((System.Runtime.InteropServices.GuidAttribute)(Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), false)[0])).Value);

                    Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == w.WikiPageId && m.IsDroppedYN == "N"));
                    wp.Title = w.Title;
                    wp.ContentText = w.ContentText.Replace("<br />", "").Replace("<p>", "").Replace("</p>", "").Replace("&amp;", "&").Replace("&nbsp;", " ");
                    wp.ModifiedDT = DateTime.Now;
                    wp.ModifiedById = (Guid)Session["UserId"];
                    wp.ModifiedByName = Session["UserFullName"].ToString();

                    Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
                    p.Title = wp.Title;
                    p.PageName = w.PageName;
                    p.MetaKeywords = w.MetaKeywords;
                    p.MetaDescription = w.MetaDescription;
                    p.PermissionId = w.PermissionId;
                    p.ModifiedDT = DateTime.Now;
                    p.ModifiedById = (Guid)Session["UserId"];
                    p.ModifiedByName = Session["UserFullName"].ToString();

                    we.SaveChanges();

                    // Index the content
                    Core.Search.SearchDoc doc = new Core.Search.SearchDoc();
                    doc.DocId = p.PageId;
                    doc.BusinessUnitId = Guid.Empty; // Search convention is Guid.EWmpty if Domain wide access
                    doc.PluginId = PluginId;
                    doc.URL = p.PageName.Substring(1);
                    doc.Title = p.Title;
                    doc.Keywords = p.MetaKeywords;
                    doc.Description = p.MetaDescription;
                    doc.Content = Core.Tools.GetTextFromHtml(wp.ContentText);
                    Core.Search.SearchEngine se = new Core.Search.SearchEngine((Guid)Session["DomainId"]);
                    se.IndexContent(doc);

                    try
                    {
                        if (!String.IsNullOrEmpty(TempData["ReturnURL"].ToString())) return Redirect(TempData["ReturnURL"].ToString());
                    }
                    catch
                    {
                    }
                    return RedirectToAction("Pages", new { id=w.WikiId});
                }
                catch (Exception e)
                {
                    ModelState.AddModelError("", Tools.ExceptionMessage(e));
                }
            }
            return View(w);
        }

        //
        // GET: /PageDetails/

        [Permission("Can Modify Domain")]
        public ActionResult PageDetails(Guid id)
        {
            WikiEntities we = new WikiEntities();
            Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == id && m.IsDroppedYN == "N"));
            Models.Wiki wiki = we.Wikis.First(m => (m.WikiId == wp.WikiId && m.IsDroppedYN == "N"));
            Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
            Wiki.Models.WikiPageUI w = new WikiPageUI();
            w.WikiId = wiki.WikiId;
            w.BusinessUnitId = wiki.BusinessUnitId;
            w.WikiHomePageId = wiki.WikiHomePageId;
            w.WikiPageId = wp.WikiPageId;
            w.WikiName = wiki.WikiName;
            w.Title = wp.Title;
            w.PageName = p.PageName;
            w.MetaKeywords = p.MetaKeywords;
            w.MetaDescription = p.MetaDescription;
            w.OnMainMenuYN = p.OnMainMenuYN;
            w.PermissionId = p.PermissionId;
            w.ContentText = wp.ContentText.Replace("\r\n", "<br />");
            ViewBag.PermissionName = we.Permissions.First(m => m.PermissionId == p.PermissionId).Name;
            return View(w);
        }

        //
        // GET: /PageDetails/

        [Permission("Can Modify Domain")]
        public ActionResult PageDelete(Guid id)
        {
            WikiEntities we = new WikiEntities();
            Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == id && m.IsDroppedYN == "N"));
            Models.Wiki wiki = we.Wikis.First(m => (m.WikiId == wp.WikiId && m.IsDroppedYN == "N"));
            Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
            Wiki.Models.WikiPageUI w = new WikiPageUI();
            w.WikiId = wiki.WikiId;
            w.BusinessUnitId = wiki.BusinessUnitId;
            w.WikiHomePageId = wiki.WikiHomePageId;
            w.WikiPageId = wp.WikiPageId;
            w.WikiName = wiki.WikiName;
            w.Title = wp.Title;
            w.PageName = p.PageName;
            w.MetaKeywords = p.MetaKeywords;
            w.MetaDescription = p.MetaDescription;
            w.OnMainMenuYN = p.OnMainMenuYN;
            w.PermissionId = p.PermissionId;
            w.ContentText = wp.ContentText.Replace("\r\n", "<br />");
            ViewBag.PermissionName = we.Permissions.First(m => m.PermissionId == p.PermissionId).Name;
            return View(w);
        }

        //
        // POST: /PageDelete/

        [HttpPost]
        [Permission("Can Modify Domain")]
        public ActionResult PageDelete(WikiPageUI w)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    WikiEntities we = new WikiEntities();
                    Core.Models.CoreEntities core = new Core.Models.CoreEntities();

                    // Get required the Guids to maintain referential integrity
                    Guid WikiPageId = w.WikiPageId;
                    Guid WikiId = w.WikiId;

                    DeleteWikiPage(we, core, WikiPageId);

                    return RedirectToAction("Pages", new { id = w.WikiId });
                }
                catch (Exception e)
                {
                    ModelState.AddModelError("", Tools.ExceptionMessage(e));
                }
            }
            return View(w);
        }

        private void DeleteWikiPage(WikiEntities we, Core.Models.CoreEntities core, Guid WikiPageId)
        {
            Models.WikiPage wp = we.WikiPages.First(m => (m.WikiPageId == WikiPageId && m.IsDroppedYN == "N"));
            wp.IsDroppedYN = "Y";
            wp.ModifiedDT = DateTime.Now;
            wp.ModifiedById = (Guid)Session["UserId"];
            wp.ModifiedByName = Session["UserFullName"].ToString();

            Models.Page p = we.Pages.First(m => (m.PageId == wp.PageId && m.IsDroppedYN == "N"));
            string pOnMainMenuYN = p.OnMainMenuYN;
            string pPageName = p.PageName;
            p.IsDroppedYN = "Y";
            p.ModifiedDT = DateTime.Now;
            p.ModifiedById = (Guid)Session["UserId"];
            p.ModifiedByName = Session["UserFullName"].ToString();

            Models.TemplateOveride to = we.TemplateOverides.First(m => (m.PageId == p.PageId && m.TemplateContentId == p.Container.ContentId && m.OverideContentId == WikiPageId));
            to.IsDroppedYN = "Y";
            to.ModifiedDT = DateTime.Now;

            we.SaveChanges();

            // Delete Mainmenu entry if Specified
            if (p.OnMainMenuYN == "Y")
            {
                string pMenuUrl = pPageName.Substring(1);
                List<Core.Models.MainMenu> mlist = core.MainMenus.Where(m => (m.URL == pMenuUrl && m.IsDroppedYN == "N")).ToList();
                if (mlist.Count > 0)
                {
                    Core.Models.MainMenu menu = mlist[0];
                    menu.IsDroppedYN = "Y";
                    menu.ModifiedDT = DateTime.Now;
                    menu.ModifiedById = (Guid)Session["UserId"];
                    menu.ModifiedByName = Session["UserFullName"].ToString();
                    core.SaveChanges();
                }
            }

            // Remove Indexed Content
            Core.Search.SearchEngine se = new Core.Search.SearchEngine((Guid)Session["DomainId"]);
            se.RemoveContent(p.PageId);
        }
        // Return Count of documents if IsReturnDocCountRequest is true.
        // Return Documents processed in this partition even if they are 0, if the partition cannot be processed return -1
        [HttpPost]
        public JsonResult Reindex(int partition, bool IsReturnDocCountRequest)
        {
            int retval = 0;
            WikiEntities we = new WikiEntities();
            Guid DomainId = (Guid)Session["DomainId"];
            if (IsReturnDocCountRequest)
            {
                List<BusinessUnit> BUList = we.BusinessUnits.Where(m => (m.DomainId == DomainId && m.IsDroppedYN == "N")).ToList();
                foreach (BusinessUnit bu in BUList)
                {
                    retval += we.WikiPages.Where(m => (m.Wiki.BusinessUnitId == bu.BusinessUnitId && m.IsDroppedYN == "N")).Count();
                }
            }
            else
            {
                retval = -1;
                List<BusinessUnit> BUList = we.BusinessUnits.Where(m => (m.DomainId == DomainId && m.IsDroppedYN == "N")).ToList();
                // Identify the BUIndex & SkipCount based on Partition & PartitionSize
                int BUIndex = 0;
                int SkipCount = 0;
                int PartitionCount = 0;
                int PartitionsUptoPrevBU = 0;
                int PageCount = 0;
                while (BUIndex < BUList.Count)
                {
                    BusinessUnit b = BUList[BUIndex];
                    PageCount = we.WikiPages.Where(m => (m.Wiki.BusinessUnitId == b.BusinessUnitId && m.IsDroppedYN == "N")).Count();
                    PartitionCount += (PageCount / PartitionSize);
                    if ((PageCount % PartitionSize) > 0) PartitionCount++;
                    if (PartitionCount >= partition)
                    {
                        //We have identified the BUIndex. Now compute SkipCount
                        SkipCount = (partition - PartitionsUptoPrevBU) * PartitionSize;
                        if (SkipCount > PageCount) return Json(retval);
                        break;
                    }
                    if (PageCount == 0) PartitionCount++; // Increment because there were no pages in that BU but it is still a partition count.
                    PartitionsUptoPrevBU += PartitionCount;
                    BUIndex++;
                }
                if (BUIndex >= BUList.Count) return Json(retval);
                Guid PluginId = new Guid(((System.Runtime.InteropServices.GuidAttribute)(Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), false)[0])).Value);
                BusinessUnit bu = BUList[BUIndex];
                List<WikiPage> pages = we.WikiPages.Where(m => (m.Wiki.BusinessUnitId == bu.BusinessUnitId && m.IsDroppedYN == "N")).OrderBy(m => m.CreateDT).Skip(SkipCount).Take(PartitionSize).ToList();
                retval = pages.Count();
                foreach (WikiPage page in pages)
                {
                    Models.Page p = we.Pages.First(m => m.PageId == page.PageId);
                    // Index the content
                    Core.Search.SearchDoc doc = new Core.Search.SearchDoc();
                    doc.DocId = p.PageId;
                    doc.BusinessUnitId = Guid.Empty; // Search convention is Guid.Empty if Domain wide access
                    doc.PluginId = PluginId;
                    doc.URL = p.PageName.Substring(1);
                    doc.Title = p.Title;
                    doc.Keywords = p.MetaKeywords;
                    doc.Description = p.MetaDescription;
                    doc.Content = Core.Tools.GetTextFromHtml(page.ContentText);
                    Core.Search.SearchEngine se = new Core.Search.SearchEngine((Guid)Session["DomainId"]);
                    se.IndexContent(doc);
                }
            }
            return Json(retval);
        }

        const int PartitionSize = 10;

        private void ReindexDocsAndPartionInfo(ref int DocumentCount, ref int PartitionCount)
        {
            DocumentCount = 0;
            PartitionCount = 0;
            int retval;
            WikiEntities we = new WikiEntities();
            Guid DomainId = (Guid)Session["DomainId"];
            List<BusinessUnit> BUList = we.BusinessUnits.Where(m => (m.DomainId == DomainId && m.IsDroppedYN == "N")).ToList();
            foreach (BusinessUnit bu in BUList)
            {
                retval = we.WikiPages.Where(m => (m.Wiki.BusinessUnitId == bu.BusinessUnitId && m.IsDroppedYN == "N")).Count();
                DocumentCount += retval;
                PartitionCount += (retval / PartitionSize);
                if ((retval % PartitionSize) > 0) PartitionCount++;
            }
        }
    }
}
